/**
 * 格式化日期时间
 * @param {Date|String|Number} date - 日期对象、时间戳或日期字符串
 * @param {String} format - 格式化模式，默认 'YYYY-MM-DD HH:mm:ss'
 * @returns {String} 格式化后的日期时间字符串
 */
export function formatDate(date, format = 'YYYY-MM-DD HH:mm:ss') {
  if (!date) return ''
  
  const d = new Date(date)
  if (isNaN(d.getTime())) return ''
  
  const year = d.getFullYear()
  const month = String(d.getMonth() + 1).padStart(2, '0')
  const day = String(d.getDate()).padStart(2, '0')
  const hours = String(d.getHours()).padStart(2, '0')
  const minutes = String(d.getMinutes()).padStart(2, '0')
  const seconds = String(d.getSeconds()).padStart(2, '0')
  
  return format
    .replace('YYYY', year)
    .replace('MM', month)
    .replace('DD', day)
    .replace('HH', hours)
    .replace('mm', minutes)
    .replace('ss', seconds)
}

/**
 * 格式化文件大小
 * @param {Number} bytes - 字节数
 * @returns {String} 格式化后的文件大小
 */
export function formatFileSize(bytes) {
  if (!bytes) return '0 B'
  
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

/**
 * 格式化数字
 * @param {Number} num - 数字
 * @param {Number} decimals - 小数位数，默认 2
 * @returns {String} 格式化后的数字字符串
 */
export function formatNumber(num, decimals = 2) {
  if (isNaN(num)) return '0'
  
  return Number(num).toFixed(decimals)
}

/**
 * 格式化百分比
 * @param {Number} num - 数字
 * @param {Number} decimals - 小数位数，默认 2
 * @returns {String} 格式化后的百分比字符串
 */
export function formatPercent(num, decimals = 2) {
  if (isNaN(num)) return '0%'
  
  return Number(num * 100).toFixed(decimals) + '%'
}

/**
 * 防抖函数
 * @param {Function} fn - 要防抖的函数
 * @param {Number} delay - 延迟时间，默认 300ms
 * @returns {Function} 防抖后的函数
 */
export function debounce(fn, delay = 300) {
  let timer = null
  
  return function(...args) {
    if (timer) clearTimeout(timer)
    
    timer = setTimeout(() => {
      fn.apply(this, args)
    }, delay)
  }
}

/**
 * 节流函数
 * @param {Function} fn - 要节流的函数
 * @param {Number} delay - 延迟时间，默认 300ms
 * @returns {Function} 节流后的函数
 */
export function throttle(fn, delay = 300) {
  let timer = null
  let lastTime = 0
  
  return function(...args) {
    const now = Date.now()
    
    if (now - lastTime > delay) {
      fn.apply(this, args)
      lastTime = now
    } else {
      if (timer) clearTimeout(timer)
      
      timer = setTimeout(() => {
        fn.apply(this, args)
        lastTime = now
      }, delay)
    }
  }
}

/**
 * 深拷贝函数
 * @param {Object} obj - 要拷贝的对象
 * @returns {Object} 拷贝后的对象
 */
export function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') return obj
  
  if (obj instanceof Date) return new Date(obj)
  if (obj instanceof Array) return obj.map(item => deepClone(item))
  if (obj instanceof RegExp) return new RegExp(obj)
  
  const cloned = {}
  for (const key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      cloned[key] = deepClone(obj[key])
    }
  }
  
  return cloned
}

/**
 * 生成随机字符串
 * @param {Number} length - 字符串长度，默认 8
 * @returns {String} 随机字符串
 */
export function randomString(length = 8) {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
  let result = ''
  
  for (let i = 0; i < length; i++) {
    result += chars.charAt(Math.floor(Math.random() * chars.length))
  }
  
  return result
}

/**
 * 生成随机颜色
 * @returns {String} 随机颜色十六进制值
 */
export function randomColor() {
  return '#' + Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0')
}

/**
 * 检查对象是否为空
 * @param {Object} obj - 要检查的对象
 * @returns {Boolean} 是否为空
 */
export function isEmpty(obj) {
  if (obj === null || obj === undefined) return true
  
  if (typeof obj === 'string' || Array.isArray(obj)) {
    return obj.length === 0
  }
  
  if (typeof obj === 'object') {
    return Object.keys(obj).length === 0
  }
  
  return false
}

/**
 * 获取URL参数
 * @param {String} name - 参数名
 * @param {String} url - URL字符串，默认为当前URL
 * @returns {String|null} 参数值
 */
export function getUrlParam(name, url = window.location.href) {
  const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)')
  const results = regex.exec(url)
  
  if (!results) return null
  if (!results[2]) return ''
  
  return decodeURIComponent(results[2].replace(/\+/g, ' '))
}

/**
 * 设置URL参数
 * @param {String} url - URL字符串
 * @param {String} key - 参数名
 * @param {String} value - 参数值
 * @returns {String} 设置参数后的URL
 */
export function setUrlParam(url, key, value) {
  const regex = new RegExp('([?&])' + key + '=.*?(&|$)', 'i')
  const separator = url.indexOf('?') !== -1 ? '&' : '?'
  
  if (url.match(regex)) {
    return url.replace(regex, '$1' + key + '=' + value + '$2')
  } else {
    return url + separator + key + '=' + value
  }
}

/**
 * 下载文件
 * @param {String} url - 文件URL
 * @param {String} filename - 文件名
 */
export function downloadFile(url, filename) {
  const link = document.createElement('a')
  link.href = url
  link.download = filename || ''
  link.style.display = 'none'
  
  document.body.appendChild(link)
  link.click()
  
  document.body.removeChild(link)
}

/**
 * 复制文本到剪贴板
 * @param {String} text - 要复制的文本
 * @returns {Promise} Promise对象
 */
export function copyToClipboard(text) {
  return new Promise((resolve, reject) => {
    try {
      const textarea = document.createElement('textarea')
      textarea.value = text
      textarea.style.position = 'fixed'
      textarea.style.opacity = '0'
      
      document.body.appendChild(textarea)
      textarea.select()
      
      document.execCommand('copy')
      document.body.removeChild(textarea)
      
      resolve()
    } catch (error) {
      reject(error)
    }
  })
}

/**
 * 获取浏览器类型
 * @returns {String} 浏览器类型
 */
export function getBrowserType() {
  const userAgent = navigator.userAgent.toLowerCase()
  
  if (userAgent.indexOf('chrome') > -1) {
    return 'chrome'
  } else if (userAgent.indexOf('firefox') > -1) {
    return 'firefox'
  } else if (userAgent.indexOf('safari') > -1) {
    return 'safari'
  } else if (userAgent.indexOf('opera') > -1) {
    return 'opera'
  } else if (userAgent.indexOf('msie') > -1 || userAgent.indexOf('trident') > -1) {
    return 'ie'
  } else {
    return 'unknown'
  }
}

/**
 * 获取操作系统类型
 * @returns {String} 操作系统类型
 */
export function getOSType() {
  const userAgent = navigator.userAgent.toLowerCase()
  
  if (userAgent.indexOf('windows') > -1) {
    return 'windows'
  } else if (userAgent.indexOf('mac') > -1) {
    return 'mac'
  } else if (userAgent.indexOf('linux') > -1) {
    return 'linux'
  } else if (userAgent.indexOf('android') > -1) {
    return 'android'
  } else if (userAgent.indexOf('ios') > -1 || userAgent.indexOf('iphone') > -1 || userAgent.indexOf('ipad') > -1) {
    return 'ios'
  } else {
    return 'unknown'
  }
}

/**
 * 检查是否为移动设备
 * @returns {Boolean} 是否为移动设备
 */
export function isMobile() {
  return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
}

/**
 * 检查是否为微信浏览器
 * @returns {Boolean} 是否为微信浏览器
 */
export function isWechat() {
  return /MicroMessenger/i.test(navigator.userAgent)
}

/**
 * 获取设备类型
 * @returns {String} 设备类型
 */
export function getDeviceType() {
  const userAgent = navigator.userAgent.toLowerCase()
  
  if (/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(userAgent)) {
    return 'tablet'
  } else if (/Mobile|Android|iP(hone|od)|IEMobile|BlackBerry|Kindle|Silk-Accelerated|(hpw|web)OS|Opera M(obi|ini)/.test(userAgent)) {
    return 'mobile'
  } else {
    return 'desktop'
  }
}

/**
 * 获取屏幕尺寸
 * @returns {Object} 屏幕尺寸对象
 */
export function getScreenSize() {
  return {
    width: window.screen.width,
    height: window.screen.height,
    availWidth: window.screen.availWidth,
    availHeight: window.screen.availHeight,
    colorDepth: window.screen.colorDepth,
    pixelDepth: window.screen.pixelDepth,
    orientation: window.screen.orientation ? window.screen.orientation.type : ''
  }
}

/**
 * 获取窗口尺寸
 * @returns {Object} 窗口尺寸对象
 */
export function getWindowSize() {
  return {
    width: window.innerWidth,
    height: window.innerHeight,
    outerWidth: window.outerWidth,
    outerHeight: window.outerHeight
  }
}